package com.zzzy.server.common.advice;

import com.zzzy.common.exception.BusinessException;
import com.zzzy.common.exception.WarningException;
import com.zzzy.common.vo.AjaxResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartException;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.util.StringJoiner;

/**
 * Description: 全局异常处理
 *
 * @author fc
 * @date 2024/4/10
 */
@Slf4j
@ControllerAdvice
public class ExceptionAdvisor {

    /**
     * 警告信息异常
     */
    @ResponseBody
    @ExceptionHandler(value = WarningException.class)
    public AjaxResult warningHandler(WarningException exception, HttpServletResponse response) {
        response.setCharacterEncoding("utf-8");
        return AjaxResult.warn(exception.getMessage());
    }

    /**
     * 上传文件过大统一异常处理
     */
    @ResponseBody
    @ExceptionHandler(value = MultipartException.class)
    public AjaxResult multipartExceptionHandler(MultipartException exception) {
        return AjaxResult.warn("上传文件过大");
    }

    /**
     * 用户操作越权
     */
    @ResponseBody
    @ExceptionHandler(value = AccessDeniedException.class)
    public AjaxResult accessDeniedExceptionHandler(AccessDeniedException exception, HttpServletResponse response) {
        response.setCharacterEncoding("utf-8");
        return AjaxResult.warn("当前用户无此操作权限");
    }
    /**
     * 其他异常
     */
    @ResponseBody
    @ExceptionHandler(value = Exception.class)
    public AjaxResult handler(Exception exception, HttpServletRequest request, HttpServletResponse response) {
        response.setCharacterEncoding("utf-8");
        String msg = "";
        if (exception instanceof BindException) {
            //参数绑定异常
            BindException e = (BindException) exception;
            FieldError fieldError = e.getBindingResult().getFieldError();
            if (fieldError.getClass() == FieldError.class){
                msg = "请求参数错误";
            } else {
                msg = e.getBindingResult().getFieldError().getDefaultMessage();
            }
        } else if (exception instanceof ConstraintViolationException) {
            //参数校验异常
            ConstraintViolationException e = (ConstraintViolationException) exception;
            StringJoiner stringJoiner = new StringJoiner(";");
            e.getConstraintViolations().forEach(error -> {
                stringJoiner.add(error.getMessage());
            });
            msg = stringJoiner.toString();
        } else if (exception instanceof HttpMessageConversionException) {
            //参数类型转换错误
            msg = "参数类型错误";
        } else if (exception instanceof MissingServletRequestParameterException) {
            //参数必传验证
            msg = "必要参数异常";
        } else if (exception instanceof HttpRequestMethodNotSupportedException) {
            //参数格式异常
            msg = "请求方式异常";
        } else if (exception instanceof BusinessException) {
            //业务异常
            BusinessException e = (BusinessException) exception;
            msg = e.getMessage();
        } else {
            msg = "服务异常，请联系管理员";
        }
        log.error("请求:{} ,异常:{}", request.getRequestURI(), msg);
        log.error("Exception:", exception);
        return AjaxResult.error(msg);
    }
}
